﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HtmlAgilityPack;
using System.IO;
using Lot.WebClient.Response;
using System.Net;
using System.Xml.Linq;
using Newtonsoft.Json.Linq;

namespace Lot.WebClient
{
    public class AdvancedWebClient
    {
        public ClientConfiguration Configuration { get; set; }

        public CookieContainer CookieContainer { get; set; }

        private RequestConfiguration requestConfiguration;       

        public AdvancedWebClient(ClientConfiguration defaultConfiguration=null,CookieContainer cookieContainer=null)
        {
            this.Configuration = defaultConfiguration ?? new ClientConfiguration();
            this.requestConfiguration = new RequestConfiguration(this.Configuration);
            this.CookieContainer = cookieContainer??new CookieContainer();
        }

        public WebClientResponse Head(string url = null)
        {
            if (url != null)
                this.requestConfiguration.Url = url;

            this.requestConfiguration.HttpMethod = HttpMethods.HEAD;

            return GetResponse();
        }

        public WebClientResponse Get(string url=null)
        {
            if (url != null)
                this.requestConfiguration.Url = url;

            this.requestConfiguration.HttpMethod = HttpMethods.GET;            

            return GetResponse();
        }

        public HtmlDocument GetHtml(string url=null,Encoding encodingOverride=null)
        {
            return Get(url).AsHtml(encodingOverride);
        }

        public XDocument GetXml(string url=null, Encoding encodingOverride = null)
        {
            return Get(url).AsXml(encodingOverride);

        }

        public JObject GetJson(string url=null, Encoding encodingOverride = null)
        {
            return Get(url).AsJson();
        }

        public String GetString(string url = null, Encoding encodingOverride = null)
        {
            return Get(url).AsString(encodingOverride);
        }

        //FLUENT
        public AdvancedWebClient Url(String url)
        {
            this.requestConfiguration.Url = url;
            return this;
        }

        public AdvancedWebClient AddQuery(String name, object value)
        {
            String v;
            if (value is string)
                v = value as string;
            else
                v = value.ToString();

            this.requestConfiguration.QueryString.Add(name, v);
            return this;
        }

        public AdvancedWebClient SetQuery(String name, object value)
        {
            String v;
            if (value is string)
                v = value as string;
            else
                v = value.ToString();

            this.requestConfiguration.QueryString.Set(name, v);
            return this;
        }

        public AdvancedWebClient Origin(String origin)
        {
            this.requestConfiguration.Origin = origin;
            return this;
        }

        public AdvancedWebClient Accept(MimeType mimeType)
        {
            this.requestConfiguration.Accept = mimeType;
            return this;
        }

        public AdvancedWebClient AcceptLanguage(String language)
        {
            this.requestConfiguration.AcceptLanguage = language;
            return this;

        }

        public AdvancedWebClient AcceptCharset(String charSet)
        {
            this.requestConfiguration.AcceptCharset = charSet;
            return this;

        }

        public AdvancedWebClient Referer(String referer)
        {
            this.requestConfiguration.Referer = referer;
            return this;
        }

        public AdvancedWebClient Host(String host)
        {
            this.requestConfiguration.Host = host;
            return this;
        }

        public AdvancedWebClient Proxy(IWebProxy proxy)
        {
            this.requestConfiguration.Proxy = proxy;
            return this;
        }

        public AdvancedWebClient AddCookie(string name, string value)
        {
            this.requestConfiguration.CookiesToSet.Add(name, value);
            return this;
        }

        //Private 

        private WebClientResponse GetResponse()
        {
            var url = this.requestConfiguration.Url;
            if (string.IsNullOrEmpty(url))
                throw new ArgumentOutOfRangeException("Url not set");

            if (!requestConfiguration.PersistCookies)
                this.CookieContainer = new System.Net.CookieContainer();

            Uri uri = new Uri(url);
            foreach (var k in this.requestConfiguration.CookiesToSet.AllKeys)
            {                
                var cookie = this.requestConfiguration.CookiesToSet[k];
                this.CookieContainer.Add(new Cookie() { Name = k, Value = cookie, Domain=uri.Host });
            }

            WebClientResponse httpResponse = null;

            httpResponse = HttpRequestEngine.GetHttpResponseSafe(url, this.CookieContainer, this.requestConfiguration);

            //reset config;
            this.requestConfiguration = new RequestConfiguration(this.Configuration);

            return httpResponse;
        }
                

    }
}
